//! 刀具库管理模块
//!
//! 提供刀具的存储、检索和选择功能，支持根据加工要求智能选择最佳刀具

use std::collections::{BTreeMap, HashMap};
use serde::{Deserialize, Serialize};
use thiserror::Error;
use crate::core::model::Material;
use crate::error::ProcessingResult;

/// 刀具类型
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum ToolType {
    Drill,      // 钻头
    EndMill,    // 端铣刀
    BallNose,   // 球头刀
    VBit,       // V型刀
    Engraver,   // 雕刻刀
    Reamer,     // 铰刀
    Tap,        // 丝锥
    Custom(u8), // 自定义类型
}

/// 切削参数
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CuttingParameters {
    /// 推荐切削速度 (米/分钟)
    pub cutting_speed: f64,

    /// 推荐每齿进给量 (毫米/齿)
    pub feed_per_tooth: f64,

    /// 最大切削深度 (毫米)
    pub max_cutting_depth: f64,

    /// 最大切削宽度 (百分比)
    pub max_cutting_width: f64,
}

/// 刀具结构体
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Tool {
    /// 刀具唯一标识
    pub id: String,

    /// 刀具类型
    pub tool_type: ToolType,

    /// 刀具直径 (毫米)
    pub diameter: f64,

    /// 刃长 (毫米)
    pub flute_length: f64,

    /// 总长 (毫米)
    pub overall_length: f64,

    /// 刀柄直径 (毫米)
    pub shank_diameter: f64,

    /// 齿数
    pub number_of_flutes: u8,

    /// 描述信息
    pub description: Option<String>,
    
    /// 当前使用时间 (分钟)
    pub usage_minutes: f64,

    /// 最大使用寿命 (分钟)
    pub max_life_minutes: Option<f64>,
}

/// 刀具选择标准
#[derive(Debug, Clone, Copy)]
pub struct ToolSelectionCriteria {
    /// 要求的刀具类型
    pub tool_type: ToolType,

    /// 最小直径要求 (毫米)
    pub min_diameter: Option<f64>,

    /// 最大直径要求 (毫米)
    pub max_diameter: Option<f64>,

    /// 所需最小刃长 (毫米)
    pub min_flute_length: Option<f64>,
    

    /// 是否优先选择新刀具
    pub prefer_new_tool: bool,
}

/// 刀具库
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ToolLibrary {
    /// 按ID索引的刀具
    by_id: HashMap<String, Tool>,

    /// 按类型和直径索引的刀具
    by_type_and_diameter: BTreeMap<(ToolType, f64), Vec<String>>,
}

/// 刀具错误类型
#[derive(Debug, Error)]
pub enum ToolError {
    #[error("刀具未找到: {0}")]
    ToolNotFound(String),

    #[error("没有合适的刀具满足要求")]
    NoSuitableTool,

    #[error("刀具直径超出范围")]
    DiameterOutOfRange,

    #[error("刀具寿命已耗尽: {0}")]
    ToolLifeExhausted(String),
}

impl ToolLibrary {
    /// 创建新的空刀具库
    pub fn new() -> Self {
        Self {
            by_id: HashMap::new(),
            by_type_and_diameter: BTreeMap::new(),
        }
    }

    /// 添加刀具到库中
    pub fn add_tool(&mut self, tool: Tool) {
        let id = tool.id.clone();
        self.by_id.insert(id.clone(), tool.clone());

        // 添加到类型/直径索引
        let key = (tool.tool_type, tool.diameter);
        self.by_type_and_diameter
            .entry(key)
            .or_insert_with(Vec::new)
            .push(id);
    }

    /// 从YAML文件加载刀具库
    pub fn from_yaml(data: &str) -> ProcessingResult<Self> {
        let tools: Vec<Tool> = serde_yaml::from_str(data)?;
        let mut library = Self::new();

        for tool in tools {
            library.add_tool(tool);
        }

        Ok(library)
    }

    /// 根据ID获取刀具
    pub fn get_by_id(&self, id: &str) -> Option<&Tool> {
        self.by_id.get(id)
    }

    /// 根据类型和直径范围获取刀具
    pub fn get_by_type_and_diameter(
        &self,
        tool_type: ToolType,
        min_diameter: Option<f64>,
        max_diameter: Option<f64>
    ) -> Vec<&Tool> {
        let mut result = Vec::new();

        // 遍历所有刀具
        for ((t, d), ids) in &self.by_type_and_diameter {
            // 检查类型匹配
            if *t != tool_type {
                continue;
            }

            // 检查直径范围
            if let Some(min) = min_diameter {
                if *d < min {
                    continue;
                }
            }

            if let Some(max) = max_diameter {
                if *d > max {
                    continue;
                }
            }

            // 添加匹配的刀具
            for id in ids {
                if let Some(tool) = self.by_id.get(id) {
                    result.push(tool);
                }
            }
        }

        result
    }

    /// 智能选择最佳刀具
    pub fn select_tool(
        &self,
        criteria: ToolSelectionCriteria
    ) -> ProcessingResult<&Tool> {
        let candidates = self.get_by_type_and_diameter(
            criteria.tool_type,
            criteria.min_diameter,
            criteria.max_diameter
        );

        if candidates.is_empty() {
            return Err(ToolError::NoSuitableTool.into());
        }

        // 过滤掉刃长不足的刀具
        let candidates: Vec<&Tool> = candidates
            .into_iter()
            .filter(|tool| {
                if let Some(min_len) = criteria.min_flute_length {
                    tool.flute_length >= min_len
                } else {
                    true
                }
            })
            .collect();

        if candidates.is_empty() {
            return Err(ToolError::NoSuitableTool.into());
        }

        // 根据选择策略排序候选刀具
        let mut sorted_candidates = candidates;

        // 排序策略:
        // 1. 优先选择直径接近最大允许值的刀具（加工效率更高）
        // 2. 优先选择新刀具（如果设置）
        // 3. 优先选择使用寿命长的刀具
        sorted_candidates.sort_by(|a, b| {
            // 直径比较（降序）
            let diameter_cmp = b.diameter.partial_cmp(&a.diameter)
                .unwrap_or(std::cmp::Ordering::Equal);

            if diameter_cmp != std::cmp::Ordering::Equal {
                return diameter_cmp;
            }

            // 使用时间比较（升序）
            if criteria.prefer_new_tool {
                let usage_cmp = a.usage_minutes.partial_cmp(&b.usage_minutes)
                    .unwrap_or(std::cmp::Ordering::Equal);

                if usage_cmp != std::cmp::Ordering::Equal {
                    return usage_cmp;
                }
            }

            // 最后按ID排序保持稳定性
            a.id.cmp(&b.id)
        });

        // 检查刀具寿命
        if let Some(tool) = sorted_candidates.first() {
            if let Some(max_life) = tool.max_life_minutes {
                if tool.usage_minutes >= max_life {
                    return Err(ToolError::ToolLifeExhausted(tool.id.clone()).into());
                }
            }
        }

        sorted_candidates.first()
            .ok_or(ToolError::NoSuitableTool.into())
            .cloned()
    }

    /// 获取刀具的切削参数
    pub fn get_cutting_parameters(
        &self,
        tool_id: &str,
        material: Material
    ) -> ProcessingResult<CuttingParameters> {
        let tool = self.get_by_id(tool_id)
            .ok_or_else(|| ToolError::ToolNotFound(tool_id.to_string()))?;

        tool.material_params.get(&material)
            .cloned()
            .ok_or_else(|| {
                ToolError::NoSuitableTool.into()
            })
    }

    /// 更新刀具使用时间
    pub fn update_tool_usage(&mut self, tool_id: &str, minutes: f64) -> ProcessingResult<()> {
        if let Some(tool) = self.by_id.get_mut(tool_id) {
            tool.usage_minutes += minutes;
            Ok(())
        } else {
            Err(ToolError::ToolNotFound(tool_id.to_string()).into()
        }
    }

    /// 获取所有刀具
    pub fn all_tools(&self) -> Vec<&Tool> {
        self.by_id.values().collect()
    }

    /// 获取特定类型的刀具
    pub fn tools_by_type(&self, tool_type: ToolType) -> Vec<&Tool> {
        self.by_id.values()
            .filter(|tool| tool.tool_type == tool_type)
            .collect()
    }
}

// 为工具库实现默认的示例数据
impl Default for ToolLibrary {
    fn default() -> Self {
        let mut library = Self::new();

        // 添加一些默认刀具
        let mut add_tool = |tool| library.add_tool(tool);

        // 钻头
        add_tool(Tool {
            id: "DRILL-3".to_string(),
            tool_type: ToolType::Drill,
            diameter: 3.0,
            flute_length: 20.0,
            overall_length: 60.0,
            shank_diameter: 3.0,
            number_of_flutes: 2,
            material: ToolMaterial::Carbide,
            coating: ToolCoating::TiN,
            description: Some("3mm 硬质合金钻头".to_string()),
            material_params: default_cutting_params(ToolType::Drill, 3.0),
            usage_minutes: 0.0,
            max_life_minutes: Some(300.0),
        });

        add_tool(Tool {
            id: "DRILL-5".to_string(),
            tool_type: ToolType::Drill,
            diameter: 5.0,
            flute_length: 30.0,
            overall_length: 70.0,
            shank_diameter: 5.0,
            number_of_flutes: 2,
            material: ToolMaterial::HighSpeedSteel,
            coating: ToolCoating::None,
            description: Some("5mm 高速钢钻头".to_string()),
            material_params: default_cutting_params(ToolType::Drill, 5.0),
            usage_minutes: 120.0,
            max_life_minutes: Some(180.0),
        });

        // 端铣刀
        add_tool(Tool {
            id: "EM-6".to_string(),
            tool_type: ToolType::EndMill,
            diameter: 6.0,
            flute_length: 25.0,
            overall_length: 60.0,
            shank_diameter: 6.0,
            number_of_flutes: 4,
            material: ToolMaterial::Carbide,
            coating: ToolCoating::TiAlN,
            description: Some("6mm 四刃平底铣刀".to_string()),
            material_params: default_cutting_params(ToolType::EndMill, 6.0),
            usage_minutes: 45.0,
            max_life_minutes: Some(600.0),
        });

        add_tool(Tool {
            id: "EM-8".to_string(),
            tool_type: ToolType::EndMill,
            diameter: 8.0,
            flute_length: 30.0,
            overall_length: 70.0,
            shank_diameter: 8.0,
            number_of_flutes: 4,
            material: ToolMaterial::Carbide,
            coating: ToolCoating::TiAlN,
            description: Some("8mm 四刃平底铣刀".to_string()),
            material_params: default_cutting_params(ToolType::EndMill, 8.0),
            usage_minutes: 200.0,
            max_life_minutes: Some(600.0),
        });

        // 球头刀
        add_tool(Tool {
            id: "BN-4".to_string(),
            tool_type: ToolType::BallNose,
            diameter: 4.0,
            flute_length: 20.0,
            overall_length: 60.0,
            shank_diameter: 4.0,
            number_of_flutes: 2,
            material: ToolMaterial::Carbide,
            coating: ToolCoating::TiCN,
            description: Some("4mm 球头铣刀".to_string()),
            material_params: default_cutting_params(ToolType::BallNose, 4.0),
            usage_minutes: 85.0,
            max_life_minutes: Some(450.0),
        });

        library
    }
}

/// 创建默认的切削参数
fn default_cutting_params(tool_type: ToolType, diameter: f64) -> HashMap<Material, CuttingParameters> {
    let mut params = HashMap::new();

    // 根据刀具类型和直径设置不同材料的参数
    let (cutting_speed, feed_per_tooth) = match tool_type {
        ToolType::Drill => (30.0 - diameter * 0.5, 0.05),
        ToolType::EndMill => (80.0 - diameter * 1.0, 0.08),
        ToolType::BallNose => (60.0 - diameter * 0.8, 0.06),
        _ => (50.0, 0.07),
    };

    // 不同材料的调整系数
    for &material in &[
        Material::Aluminum,
        Material::Steel,
        Material::Wood,
        Material::Plastic
    ] {
        let material_factor = match material {
            Material::Aluminum => 1.2,
            Material::Steel => 0.8,
            Material::Wood => 1.5,
            Material::Plastic => 1.1,
            Material::Composite => 0.9,
            _ => 1.0,
        };

        let max_cutting_depth = match tool_type {
            ToolType::Drill => diameter * 5.0,
            ToolType::EndMill => diameter * 0.5,
            ToolType::BallNose => diameter * 0.3,
            _ => diameter,
        };

        params.insert(material, CuttingParameters {
            cutting_speed: cutting_speed * material_factor,
            feed_per_tooth: feed_per_tooth * material_factor,
            max_cutting_depth,
            max_cutting_width: 0.8, // 80% 刀具直径
        });
    }

    params
}